/**
 * Program : Lembar Kerja 04, Hierarchical Modelling
 *           Lighting, Shadow, and Texture, Worksheet 4
 * Berkas  : drawspart_spider.h
 * ----------------------------------------------
 * Nama Pembuat :
 *  - Andry Luthfi, (0906629044)
 *  - Hadi Saputro, (0906562871)
 *
 * Aplikasi ini mengimplementasikan konsep Objek Hirarkis
 * serta teknik-teknik pencahayaan pada OpenGL. konsep-konsep
 * didapatkan pada mata kuliah Grafika Komputer.
 *
 *
 * Hak Cipta (c) 2012, Andry Luthfi, Hadi Saputro
 */

/* definisi ukuran body spider */
#define TORSO_HEIGHT 5.0
#define TORSO_RADIUS 5.0

/* definisi ukuran untuk kaki depan */
#define UPPER_ARM_HEIGHT 5.0
#define LOWER_ARM_HEIGHT 5.0
#define UPPER_ARM_RADIUS  0.5
#define LOWER_ARM_RADIUS  0.5

/* definisi ukuran untuk kaki belakang */
#define UPPER_LEG_RADIUS  0.5
#define LOWER_LEG_RADIUS  0.5
#define LOWER_LEG_HEIGHT 5.0
#define UPPER_LEG_HEIGHT 5.0

/* definisi ukuran untuk kepala */
#define HEAD_HEIGHT 2.0
#define HEAD_RADIUS 2.0

void glutWireCylinder(GLUquadricObj *obj, GLdouble base, GLdouble top, GLdouble height, GLint slices,  GLint stacks);

// atribut theta sebagai sudut rotasi (engsel / sudut persambungan)
/*static GLfloat theta[11] = {0.0, // sudut untuk pergerakan body
                            0.0, // sudut pergerakan kepala ke atas-bawah
                            0.0, // sudut pergerakan kepala ke kanan-kiri
                            -30.0, // sudut persambungan kaki depan kiri atas dengan body
                            120.0, // sudut persambungan kaki depan kiri bawah dengan atas
                            30.0,   // sudut persambungan kaki depan kanan atas dengan body
                            -120.0, // sudut persambungan kaki depan kanan bawah dengan atas
                            -30.0, // sudut persambungan kaki belakang kiri atas dengan body
                            120.0, // sudut persambungan kaki belakang kiri bawah dengan atas
                            30.0, // sudut persambungan kaki belakang kanan atas dengan body
                            -120.0 // sudut persambungan kaki belakang kanan bawah dengan atas
                           }; /* initial joint angles */
// quadric object masing-masing model
GLUquadricObj *t,    // quadric objek untuk torso / body
              *h,    // quadric objek untuk kepala
              *lua,  // quadric objek untuk kaki depan kiri atas
              *lla,  // quadric objek untuk kaki depan kiri bawah
              *rua,  // quadric objek untuk kaki depan kanan atas
              *rla,  // quadric objek untuk kaki depan kanan bawah
              *lll,  // quadric objek untuk kaki belakang kiri atas
              *rll,  // quadric objek untuk kaki belakang kiri bawah
              *rul,  // quadric objek untuk kaki belakang kanan atas
              *lul;  // quadric objek untuk kaki belakang kanan bawah

// inisialisasi untuk objek spider
void initSpider() {
    h=gluNewQuadric();
    gluQuadricDrawStyle(h, GLU_FILL);
    t=gluNewQuadric();
    gluQuadricDrawStyle(t, GLU_FILL);
    lua=gluNewQuadric();
    gluQuadricDrawStyle(lua, GLU_FILL);
    lla=gluNewQuadric();
    gluQuadricDrawStyle(lla, GLU_FILL);
    rua=gluNewQuadric();
    gluQuadricDrawStyle(rua, GLU_FILL);
    rla=gluNewQuadric();
    gluQuadricDrawStyle(rla, GLU_FILL);
    lul=gluNewQuadric();
    gluQuadricDrawStyle(lul, GLU_FILL);
    lll=gluNewQuadric();
    gluQuadricDrawStyle(lll, GLU_FILL);
    rul=gluNewQuadric();
    gluQuadricDrawStyle(rul, GLU_FILL);
    rll=gluNewQuadric();
    gluQuadricDrawStyle(rll, GLU_FILL);
}

// menggambar torso (body) spider
void torso() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[0]);
    }

    glPushMatrix();
        glScalef(TORSO_RADIUS, TORSO_HEIGHT, TORSO_RADIUS);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidSphere(1.0, 10, 10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireSphere(1.0, 10, 10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kepala spider
void head() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[1]);
    }

    glPushMatrix();
        glTranslatef(0.0, 0.5*HEAD_HEIGHT,0.0);
        glTranslatef(0.0, 0.0, TORSO_RADIUS);
        glScalef(HEAD_RADIUS, HEAD_HEIGHT, HEAD_RADIUS);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidSphere(1.0,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireSphere(1.0,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki depan bagian kiri atas
void left_upper_arm() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(lua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(lua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki depan bagian kiri bawah
void left_lower_arm() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(lla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(lla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki depan bagian kanan atas
void right_upper_arm() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(rua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(rua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki depan bagian kanan bawah
void right_lower_arm() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(rla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(rla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki belakang bagian kiri atas
void left_upper_leg() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(lul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(lul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki belakang bagian kiri bawah
void left_lower_leg() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(lll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(lll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki belakang bagian kanan atas
void right_upper_leg() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(rul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(rul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10);
        }
    glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar kaki belakang bagian kanan bawah
void right_lower_leg() {
    if (isTexture_s){
        glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
		glBindTexture(GL_TEXTURE_2D, texture[4]);
    }

    glPushMatrix();
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        if(OBJECT_MODE == OBJECT_SHADING) {
            glutSolidCylinder(rll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10);
        }
        else if(OBJECT_MODE == OBJECT_WIREFRAME) {
            glutWireCylinder(rll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10);
        }
        glPopMatrix();

    if (isTexture_s){
        glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S ( NEW )
		glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T ( NEW )
    }
}

// menggambar objek spider (menyatukan bagian-bagian spider)
void renderObjectSpider() {
    glPushMatrix();
    glRotatef(theta[0], 0.0, 1.0, 0.0);
    torso();

    // set material berupa gold
    if (!isTexture_s) {
        glMaterialfv(GL_FRONT, GL_SPECULAR, gold_specular);
        glMaterialfv(GL_FRONT, GL_AMBIENT, gold_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, gold_diffuse);
        glMaterialf(GL_FRONT, GL_SHININESS, gold_shininess);
    }

    glPushMatrix();
    glTranslatef(0.0, 0.0, 0.0);
    glRotatef(theta[1], 1.0, 0.0, 0.0);
    glRotatef(theta[2], 0.0, 1.0, 0.0);
    glTranslatef(0.0, -0.5*HEAD_HEIGHT, 0.0);
    head();
    glPopMatrix();

    if (!isTexture_s) {
    // set material berupa pearl
        glMaterialfv(GL_FRONT, GL_SPECULAR, pearl_specular);
        glMaterialfv(GL_FRONT, GL_AMBIENT, pearl_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, pearl_diffuse);
        glMaterialf(GL_FRONT, GL_SHININESS, pearl_shininess);
    }

    glPushMatrix();
    glRotatef(90, 0.0, 0.0, 1.0);
    glTranslatef(-0.5*TORSO_RADIUS, 0.5*TORSO_HEIGHT, 2.5);
    //
    glRotatef(theta[3], 0.0, 0.0, 1.0);
    //printf("%.0f\n", theta[3]);
    left_upper_arm();

    glTranslatef(0.0, 0.93*UPPER_ARM_HEIGHT, 0.0);
    glRotatef(theta[4], 0.0, 0.0, 1.0);
    left_lower_arm();

    glPopMatrix();
    glPushMatrix();
    glRotatef(-90, 0.0, 0.0, 1.0);
    glTranslatef(0.5*TORSO_RADIUS, 0.5*TORSO_HEIGHT, 2.5);
    glRotatef(theta[5], 0.0, 0.0, 1.0);
    right_upper_arm();

    glTranslatef(0.0, 0.93*UPPER_ARM_HEIGHT, 0.0);
    glRotatef(theta[6], 0.0, 0.0, 1.0);
    right_lower_arm();

    glPopMatrix();

    if (!isTexture_s) {
    // set material berupa pewter
        glMaterialfv(GL_FRONT, GL_SPECULAR, pewter_specular);
        glMaterialfv(GL_FRONT, GL_AMBIENT, pewter_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, pewter_diffuse);
        glMaterialf(GL_FRONT, GL_SHININESS, pewter_shininess);
    }

    glPushMatrix();
    glRotatef(90, 0.0, 0.0, 1.0);
    glTranslatef(-0.5*TORSO_RADIUS, 0.5*TORSO_HEIGHT, -2.5);
    glRotatef(theta[7], 0.0, 0.0, 1.0);
    left_upper_leg();

    glTranslatef(0.0, 0.93*UPPER_LEG_HEIGHT, 0.0);
    glRotatef(theta[8], 0.0, 0.0, 1.0);
    left_lower_leg();

    glPopMatrix();
    glPushMatrix();
    glRotatef(-90, 0.0, 0.0, 1.0);
    glTranslatef(0.5*TORSO_RADIUS, 0.5*TORSO_HEIGHT, -2.5);
    glRotatef(theta[9], 0.0, 0.0, 1.0);
    right_upper_leg();

    glTranslatef(0.0, 0.93*UPPER_LEG_HEIGHT, 0.0);
    glRotatef(theta[10], 0.0, 0.0, 1.0);
    right_lower_leg();

    glPopMatrix();
    glPopMatrix();
}

void renderShadowSpider() {
// membuat bayangan
    glDisable(GL_LIGHTING);
    glColor3f(0.0, 0.0, 0.0);

    if (isLight[0]) {
        // perbaharui posisi lampu
        updRotationAngle();
        // proyeksikan bayanagan ke tembok belakang
        glPushMatrix();
        glShadowProjection(lamp1_pos, backPointRot, backNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke tembok kiri
        glPushMatrix();
        glShadowProjection(lamp1_pos, leftPointRot, leftNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke tembok kanan
        glPushMatrix();
        glShadowProjection(lamp1_pos, rightPointRot, rightNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke lantai
        glPushMatrix();
        glShadowProjection(lamp1_pos, floorPointRot, floorNormal);
        renderObjectSpider();
        glPopMatrix();
    }

    if (isLight[1]) {
        // proyeksikan bayanagan ke tembok kiri
        glPushMatrix();
        glShadowProjection(lamp3_pos, leftPointRot, leftNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke tembok kanan
        glPushMatrix();
        glShadowProjection(lamp3_pos, rightPointRot, rightNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke lantai
        glPushMatrix();
        glShadowProjection(lamp3_pos, floorPointRot, floorNormal);
        renderObjectSpider();
        glPopMatrix();
    }

    if (isLight[2]) {
        // proyeksikan bayanagan ke tembok kanan
        glPushMatrix();
        glShadowProjection(lamp2_pos, rightPointRot, rightNormal);
        renderObjectSpider();
        glPopMatrix();

        // proyeksikan bayanagan ke lantai
        glPushMatrix();
        glShadowProjection(lamp2_pos, floorPointRot, floorNormal);
        renderObjectSpider();
        glPopMatrix();
    }

    if (isLight[3]) {
        glPushMatrix();
        glShadowProjection(lamp4_pos, leftPointRot, leftNormal);
        renderObjectSpider();
        glPopMatrix();

        glPushMatrix();
        glShadowProjection(lamp4_pos, floorPointRot, floorNormal);
        renderObjectSpider();
        glPopMatrix();
    }
}


void animateSpinningSpider() {
    // mengatur sudut perputaran spider
    switch(s_angle) {

        case 0:
            theta[s_angle]+= inc;
            if (theta[s_angle] >= 360) theta[s_angle] -= 360;
            break;

        case 1: case 2: case 3: case 5:
            // up = true;
            if (up) {
                theta[s_angle]-= inc;
                if (theta[s_angle] <= -30.0) up = false;
                if (s_angle == 3 || s_angle == 5) theta[s_angle+4]-= inc;
            }
            if (!up) {
                theta[s_angle]+= inc;
                if (theta[s_angle] >= 30.0) up = true;
                if (s_angle == 3 || s_angle == 5) theta[s_angle+4]+= inc;
            }
            break;

        case 4:
            //up = true;
            if (up) {
                theta[s_angle]-= inc;
                theta[s_angle+4]-= inc;
                if (theta[s_angle] <= -30.0) up = false;
            }
            if (!up) {
                theta[s_angle]+= inc;
                theta[s_angle+4]+= inc;
                if (theta[s_angle] >= 120.0) up = true;
            }
            break;

        case 6:
            //up = true;
            if (up) {
                theta[s_angle]-= inc;
                theta[s_angle+4]-= inc;
                if (theta[s_angle] <= -120.0) up = false;
            }
            if (!up) {
                theta[s_angle]+= inc;
                theta[s_angle+4]+= inc;
                if (theta[s_angle] >= 30.0) up = true;
            }
            break;
    }
}
